# -*- coding: utf-8 -*-
#===============================================================================
# Koro Business Environment
# Copyright (C) 2008,2010  Antonio Corroppoli
#
#This file is part of Koro BE.
# 
# Koro BE is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
# 
# Koro BE is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with Koro BE; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
#===============================================================================
'''
Created on 04/nov/2010

@author: antstud
'''

import sys
import decimal
import datetime
#from koro import ROUND
import koro
from koro.core import exception
ROUND=None

def get_options():
    return koro._get_options()

def newlinechar():
    import sys
    if 'linux' in sys.platform:
        return '\n'
    return '\r\n'
        

def default_if_none(val,default):
    '''Restituisce il valore di default se il parametro val e' None o
    se not val restituisce True.
    Restituisce val altrimenti.'''
    if val is None or not val:
        return default
    return val

def none_if_not(val):
    '''Restituisce None se not val restituisce True. 
    Restituisce val altrimenti.'''
    if not val or val=='None':
        return None
    return val

def round_up(value):
    assert isinstance(value,decimal.Decimal)    
    return value.quantize(decimal.Decimal('1.00'),rounding=decimal.ROUND_UP)

def round_down(value):
    assert isinstance(value,decimal.Decimal)
    return value.quantize(decimal.Decimal('1.00'),rounding=decimal.ROUND_DOWN)

def no_round(value):
    assert isinstance(value,decimal.Decimal)
    return value.quantize(decimal.Decimal('1.00'))

def round(value):
    value=to_decimal(value)
    global ROUND
    if ROUND is None:
        ROUND=koro._get_option('ROUND')
    if ROUND.lower() == 'up':
        return round_up(value)
    elif ROUND.lower() == 'down':
        return round_down(value)
    elif ROUND.lower() == 'no':
        return no_round(value)
    else:
        raise Exception("Invalid round value: '{0}'.".format(ROUND))
    
def to_bool_old(val):
    if val==u'False' or val=='None':
        return False
    if val==u'True':
        return True
    return bool(val)

def to_bool(val):
    try:
        val=val.lstrip()
        val=eval(val)
    except:
        pass
    return bool(val)

def to_string(val):
    return unicode(str(val),'utf-8')

def to_date(date):
    if isinstance(date,basestring):
        y,m,d=date.split('-')
        date=datetime.date(int(y),int(m),int(d))
    return date

def to_decimal(val):
    if isinstance(val,float) or isinstance(val,int):
        val=decimal.Decimal(str(val))
    elif isinstance(val,basestring):
        val=decimal.Decimal(val)
    
    return decimal.Decimal(moneyfmt(val,sep='',dp='.'))

def format_date(date,sep='/'):
    format='%d{0}%m{0}%Y'.format(sep)
    if isinstance(date,basestring):
        date=to_date(date)
    return date.strftime(format)

def euro(value):
    return moneyfmt(to_decimal(value),curr=koro.ksettings.EURO)

def moneyfmt(value, places=2, curr='', sep='.', dp=',',
             pos='', neg='-', trailneg=''):
    """Convert Decimal to a money formatted string.

    places:  required number of places after the decimal point
    curr:    optional currency symbol before the sign (may be blank)
    sep:     optional grouping separator (comma, period, space, or blank)
    dp:      decimal point indicator (comma or period)
             only specify as blank when places is zero
    pos:     optional sign for positive numbers: '+', space or blank
    neg:     optional sign for negative numbers: '-', '(', space or blank
    trailneg:optional trailing minus indicator:  '-', ')', space or blank

    >>> d = Decimal('-1234567.8901')
    >>> moneyfmt(d, curr='$')
    '-$1,234,567.89'
    >>> moneyfmt(d, places=0, sep='.', dp='', neg='', trailneg='-')
    '1.234.568-'
    >>> moneyfmt(d, curr='$', neg='(', trailneg=')')
    '($1,234,567.89)'
    >>> moneyfmt(Decimal(123456789), sep=' ')
    '123 456 789.00'
    >>> moneyfmt(Decimal('-0.02'), neg='<', trailneg='>')
    '<0.02>'

    """
    q = decimal.Decimal(10) ** -places      # 2 places --> '0.01'
    sign, digits, exp = value.quantize(q).as_tuple()
    result = []
    digits = map(str, digits)
    build, next = result.append, digits.pop
    if sign:
        build(trailneg)
    for i in range(places):
        build(next() if digits else '0')
    build(dp)
    if not digits:
        build('0')
    i = 0
    while digits:
        build(next())
        i += 1
        if i == 3 and digits:
            i = 0
            build(sep)
    build(curr)
    build(neg if sign else pos)
    return ''.join(reversed(result))


def validate_sconti(sconti):
    if sconti == '':
        return True
    sconti.replace('%','')
    last = False
    if not is_number(sconti[0]) or not is_number(sconti[-1]):
        raise exception.KoroValidationError('Sconti: formato non valido.')
    for c in sconti:
        if (not is_number(c) and c != '+' and c != '-') or (not is_number(c) and last):
            raise exception.KoroValidationError('Sconti: formato non valido.')
        if c == '+' or c == '-':
            last = True
        else:
            last = False            
    return True    
#    try:
#        token_list = sconti.split('+')
#        for token in token_list:
#            int(token)
#    except AttributeError, ValueError:
#        raise exception.KoroValidationError('Sconti: formato non valido.')

def tokenizer_sconti(sconti):
    '''Riceve gli sconti in un formato validato.'''
    token_list = []
    token = ''
    for c in sconti:
        if is_number(c):
            token += c
        elif c != '+' and c != '-':
            raise exception.KoroValidationError('Sconti: formato non valido.')
        else:
            token_list.append(int(token))
            token_list.append(c)
            token = ''
    if is_number(token):
        token_list.append(int(token))
    return token_list

def is_number(token):
    if token == '':
        return False
    for c in token:
        if not (ord(c) >= 48 and ord(c) <= 57):
            return False
    return True

def is_admin():
    if len(sys.argv) > 1 and sys.argv[1].startswith('--admin'):
        return True
    return False


#===============================================================================
# KoroList
#===============================================================================
class KoroList(list):
    '''L'unica differenza conla lista builtin è che non si
    possono appendere item None.''' 
    def __init__(self):
        super(KoroList,self).__init__()
        
    def append(self,item):
        if item is None:
            return
        super(KoroList,self).append(item)